home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Tools / Useful / AmiCDROM / src / devsupp.c < prev    next >
C/C++ Source or Header  |  1994-11-03  |  15KB  |  538 lines

  1. /* devsupp.c:
  2.  *
  3.  * Support routines for the device handler.
  4.  * - debugging
  5.  * - Mountlist "Startup" field parsing
  6.  *
  7.  * ----------------------------------------------------------------------
  8.  * This code is (C) Copyright 1993,1994 by Frank Munkert.
  9.  * All rights reserved.
  10.  * This software may be freely distributed and redistributed for
  11.  * non-commercial purposes, provided this notice is included.
  12.  * ----------------------------------------------------------------------
  13.  * History:
  14.  * 
  15.  * 12-Oct-94   fmu   Get_Startup() modified.
  16.  * 17-May-94   fmu   New option MAYBELOWERCASE (=ML).
  17.  * 09-Apr-94   fmu   Larger buffer for startup strings.
  18.  * 02-Jan-94   fmu   New options XPOS and YPOS.
  19.  * 11-Dec-93   fmu   Memory type can now be chosen by the user:
  20.  *                   new options CHIP, DMA and ANY.
  21.  * 11-Dec-93   fmu   The assembly code stubs for the debugging process
  22.  *                   are no longer necessary; the debugger code is now
  23.  *                   called with CreateNewProcTags().
  24.  * 21-Nov-93   fmu   New option SCANINTERVAL.
  25.  * 14-Nov-93   fmu   Added Handle_Control_Packet for 'cdcontrol' program.
  26.  * 10-Nov-93   fmu   New options SHOWVERSION and HFSFIRST.
  27.  * 23-Oct-93   fmu   MacHFS options added.
  28.  * 15-Oct-93   fmu   Adapted to new VOLUME structure.
  29.  */
  30.  
  31. /*
  32.  * Extract information from Mountlist "Startup" field.
  33.  */
  34.  
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <stdarg.h>
  38. #include <stdio.h>
  39.  
  40. #include <exec/types.h>
  41. #include <dos/dostags.h>
  42.  
  43. #include "device.h"
  44. #include "devsupp.h"
  45. #include "intui.h"
  46. #include "params.h"
  47. #include "cdcontrol.h"
  48.  
  49. static char *TheVersion = "$VER: " VERSION;
  50.  
  51. unsigned long g_memory_type;
  52. short g_retry_mode;
  53.  
  54. int
  55. Get_Startup (LONG p_startup)
  56. {
  57.   enum {
  58.     ARG_DEVICE,
  59.     ARG_UNIT,
  60.     ARG_CHIP,
  61.     ARG_FAST,
  62.     ARG_DMA,
  63.     ARG_ANY,
  64.     ARG_RETRY,
  65.     ARG_LOWERCASE,
  66.     ARG_MAYBELOWERCASE,
  67.     ARG_ROCKRIDGE,
  68.     ARG_TRACKDISK,
  69.     ARG_MACTOISO,
  70.     ARG_CONVERTSPACES,
  71.     ARG_SHOWVERSION,
  72.     ARG_HFSFIRST,
  73.     ARG_STDBUFFERS,
  74.     ARG_FILEBUFFERS,
  75.     ARG_DATAEXT,
  76.     ARG_RESOURCEEXT,
  77.     ARG_SCANINTERVAL,
  78.     ARG_PLAYCDDA,
  79.     ARG_XPOS,
  80.     ARG_YPOS,
  81.     ARGCOUNT
  82.   };
  83.  
  84.   STRPTR Args[ARGCOUNT],Index;
  85.   static UBYTE LocalBuffer[250];
  86.   struct RDArgs *ArgsPtr;
  87.   int result = FALSE,len,i;
  88.   int cnt;
  89.  
  90.   /* Clear the argument vector. */
  91.   memset (Args, 0, sizeof(Args));
  92.  
  93.   /* valid startup entry? */
  94.   if (!p_startup) {
  95.     Display_Error ("Filesystem startup entry invalid");
  96.     return FALSE;
  97.   }
  98.  
  99.   if (p_startup != -1) {
  100.   
  101.     /* Get the contents of the startup field. */
  102.     len = ((STRPTR)(BADDR(p_startup)))[0];
  103.     if (len > sizeof (LocalBuffer) - 1)
  104.       len = sizeof (LocalBuffer) - 1;
  105.     memcpy (LocalBuffer, ((STRPTR)(BADDR(p_startup))) + 1, len);
  106.  
  107.     /* Provide null-termination. */
  108.     LocalBuffer[len] = 0;
  109.  
  110.     /* Remove leading quotes. */
  111.     for (i = 0 ; i < len ; i++) {
  112.       if (LocalBuffer[i] != ' ') {
  113.         if (LocalBuffer[i] == '\"')
  114.       LocalBuffer[i] = ' ';
  115.         break;
  116.       }
  117.     }
  118.     
  119.  
  120.     /* Remove trailing quotes. */
  121.     for (i = len - 1 ; i >= 0 ; i--) {
  122.       if (LocalBuffer[i] != ' '){
  123.         if (LocalBuffer[i] == '\"')
  124.       LocalBuffer[i] = ' ';
  125.         break;
  126.       }
  127.     }
  128.  
  129.     /* Replace "-" by spaces, except "--" which is replaced by "-". */
  130.     Index = LocalBuffer;
  131.     for (i = 0 ; i < len ; i++) {
  132.       if (LocalBuffer[i] == '-') {
  133.         if (i+1 < len && LocalBuffer[i+1] == '-') {
  134.           *Index++ = '-';
  135.       i++;
  136.         } else
  137.           *Index++ = ' ';
  138.       } else
  139.         *Index++ = LocalBuffer[i];
  140.     }
  141.  
  142.     /* Provide null-termination. */
  143.     *Index = 0;
  144.  
  145.     /* Don't forget the newline, or ReadArgs won't work. */
  146.     strcat ((char *) LocalBuffer, "\n");
  147.     
  148.   }
  149.  
  150.   if (ArgsPtr = (struct RDArgs *) AllocDosObjectTags (DOS_RDARGS,TAG_DONE)) {
  151.  
  152.     /* Don't prompt for input! */
  153.     ArgsPtr -> RDA_Flags |= RDAF_NOPROMPT;
  154.  
  155.     /* Set up for local parsing. */
  156.     ArgsPtr->RDA_Source.CS_Buffer = LocalBuffer;
  157.     ArgsPtr->RDA_Source.CS_Length = strlen ((char *) LocalBuffer);
  158.     ArgsPtr->RDA_Source.CS_CurChr = 0;
  159.  
  160.     /* Read the arguments. */
  161.     if (ReadArgs ((UBYTE *)
  162.                 "D=DEVICE,U=UNIT/N,C=CHIP/S,F=FAST/S,DMA/S,ANY/S,"
  163.           "RETRY/S,L=LOWERCASE/S,ML=MAYBELOWERCASE/S,"
  164.              "R=ROCKRIDGE/S,T=TRACKDISK/S,"
  165.           "MI=MACTOISO/S,CS=CONVERTSPACES/S,"
  166.           "SV=SHOWVERSION/S,HF=HFSFIRST/S,"
  167.           "SB=STDBUFFERS/K/N,FB=FILEBUFFERS/K/N,"
  168.           "DE=DATAEXT/K,RE=RESOURCEEXT/K,"
  169.           "SI=SCANINTERVAL/K/N,PC=PLAYCDDA/K,"
  170.           "X=XPOS/K/N,Y=YPOS/K/N",
  171.           (LONG *) Args, ArgsPtr)) {
  172.       result = TRUE;
  173.  
  174.       if (Args[ARG_DEVICE]) {
  175.         len = strlen((char *) (Args[ARG_DEVICE]));
  176.  
  177.         if (len >= sizeof (g_device)) {
  178.        Display_Error ("Device name entry too long");
  179.        result = FALSE;
  180.         } else
  181.       strcpy (g_device, (char *) (Args[ARG_DEVICE]));
  182.       } else {
  183.         Display_Error("Device name entry missing");
  184.     result = FALSE;
  185.       }
  186.  
  187.       g_unit = *(long *) (Args[ARG_UNIT]);
  188.  
  189.       g_memory_type = MEMF_CHIP;
  190.       cnt = 0;
  191.       if (Args[ARG_FAST] != NULL) {
  192.         g_memory_type = MEMF_FAST;
  193.     cnt++;
  194.       }
  195.       if (Args[ARG_CHIP] != NULL) {
  196.         g_memory_type = MEMF_CHIP;
  197.     cnt++;
  198.       }
  199.       if (Args[ARG_DMA] != NULL) {
  200.         g_memory_type = MEMF_24BITDMA;
  201.     cnt++;
  202.       }
  203.       if (Args[ARG_ANY] != NULL) {
  204.         g_memory_type = MEMF_ANY;
  205.     cnt++;
  206.       }
  207.       if (cnt > 1) {
  208.         Display_Error ("Only ONE memory option may be used!");
  209.     result = FALSE;
  210.       }
  211.  
  212.       g_retry_mode = (Args[ARG_RETRY] != NULL);
  213.       g_map_to_lowercase = (Args[ARG_LOWERCASE] != NULL);
  214.       g_maybe_map_to_lowercase = (Args[ARG_MAYBELOWERCASE] != NULL);
  215.  
  216.       if (g_map_to_lowercase && g_maybe_map_to_lowercase) {
  217.         Display_Error ("Options L and ML are mutually exclusive!");
  218.     result = FALSE;
  219.       }
  220.  
  221.       g_use_rock_ridge = (Args[ARG_ROCKRIDGE] != NULL);
  222.       g_trackdisk = (Args[ARG_TRACKDISK] != NULL);
  223.       g_show_version_numbers = (Args[ARG_SHOWVERSION] != NULL);
  224.       g_hfs_first = (Args[ARG_HFSFIRST] != NULL);
  225.  
  226.       if (Args[ARG_STDBUFFERS]) {      
  227.         g_std_buffers = *(long *) (Args[ARG_STDBUFFERS]);
  228.         if (g_std_buffers <= 0) {
  229.           Display_Error ("Illegal number of standard buffers: %ld", g_std_buffers);
  230.       result = FALSE;
  231.         }
  232.       } else
  233.         g_std_buffers = 5;
  234.       
  235.       if (Args[ARG_FILEBUFFERS]) {
  236.         g_file_buffers = *(long *) (Args[ARG_FILEBUFFERS]);
  237.         if (g_file_buffers <= 0) {
  238.           Display_Error ("Illegal number of file buffers: %ld", g_std_buffers);
  239.       result = FALSE;
  240.         }
  241.       } else
  242.         g_file_buffers = 5;
  243.  
  244.       if (Args[ARG_DATAEXT])
  245.         strcpy (g_data_fork_extension, (char *) Args[ARG_DATAEXT]);
  246.  
  247.       if (Args[ARG_RESOURCEEXT])
  248.         strcpy (g_resource_fork_extension, (char *) Args[ARG_RESOURCEEXT]);
  249.  
  250.       g_convert_hfs_filenames = (Args[ARG_MACTOISO] != NULL);
  251.       g_convert_hfs_spaces = (Args[ARG_CONVERTSPACES] != NULL);
  252.  
  253.       if (Args[ARG_SCANINTERVAL]) {
  254.         g_scan_interval = *(long *) (Args[ARG_SCANINTERVAL]);
  255.         if (g_scan_interval < 0)
  256.           g_scan_interval = 0;
  257.       } else
  258.         g_scan_interval = 3;
  259.  
  260.       if (Args[ARG_PLAYCDDA]) {
  261.         len = strlen((char *) (Args[ARG_PLAYCDDA]));
  262.  
  263.         if (len >= sizeof (g_play_cdda_command)) {
  264.        Display_Error ("PLAYCDDA command name too long");
  265.        result = FALSE;
  266.         } else
  267.       strcpy (g_play_cdda_command, (char *) (Args[ARG_PLAYCDDA]));
  268.       } else
  269.         g_play_cdda_command[0] = 0;
  270.  
  271.       if (Args[ARG_XPOS])
  272.         g_xpos = *(long *) (Args[ARG_XPOS]);
  273.       if (Args[ARG_YPOS])
  274.         g_ypos = *(long *) (Args[ARG_YPOS]);
  275.  
  276.       FreeArgs(ArgsPtr);
  277.     } else {
  278.       Fault(IoErr (), (UBYTE *) "", LocalBuffer, sizeof (LocalBuffer));
  279.       Display_Error ("Error while parsing \"Startup\" field in Mountlist:\n%s",
  280.                    LocalBuffer + 2);
  281.     }
  282.  
  283.     FreeDosObject (DOS_RDARGS, ArgsPtr);
  284.   } else
  285.     Display_Error ("Out of memory");
  286.  
  287.   if (!result)
  288.     return FALSE;
  289.  
  290.   if (g_cd = Open_CDROM (g_device, g_unit, g_trackdisk, g_memory_type,
  291.                   g_std_buffers, g_file_buffers)) {
  292.  
  293.     g_disk_inserted = (Test_Unit_Ready (g_cd) ||
  294.                    Test_Unit_Ready (g_cd));
  295.  
  296.     return TRUE;
  297.   } else {
  298.  
  299.     if (g_retry_mode &&
  300.     g_cdrom_errno != CDROMERR_NO_MEMORY &&
  301.     g_cdrom_errno != CDROMERR_MSGPORT &&
  302.     g_cdrom_errno != CDROMERR_IOREQ) {
  303.       return TRUE;
  304.     }
  305.  
  306.     switch (g_cdrom_errno) {
  307.     case CDROMERR_NO_MEMORY:
  308.       Display_Error ("Out of memory: cannot allocate buffers\n"
  309.                  "(Try CHIP, FAST, DMA or ANY option.)");
  310.       break;
  311.     case CDROMERR_MSGPORT:
  312.       Display_Error ("Cannot open the message port.");
  313.       break;
  314.     case CDROMERR_IOREQ:
  315.       Display_Error ("Cannot open the I/O request structure.");
  316.       break;
  317.     case CDROMERR_DEVICE:
  318.       Display_Error ("Cannot open \"%s\" unit %ld", g_device, (int) g_unit);
  319.       break;
  320.     case CDROMERR_BLOCKSIZE:
  321.       Display_Error ("Cannot access CDROM drive: illegal blocksize.");
  322.       break;
  323.     default:
  324.       break;
  325.     }
  326.     return FALSE;
  327.   }
  328. }
  329.  
  330. int Handle_Control_Packet (ULONG p_type, ULONG p_par1, ULONG p_par2)
  331. {
  332.   switch (p_type) {
  333.   case CDCMD_LOWERCASE:
  334.     g_map_to_lowercase = p_par1;
  335.     break;
  336.   case CDCMD_MACTOISO:
  337.     g_convert_hfs_filenames = p_par1;
  338.     break;
  339.   case CDCMD_CONVERTSPACES:
  340.     g_convert_hfs_spaces = p_par1;
  341.     break;
  342.   case CDCMD_SHOWVERSION:
  343.     g_show_version_numbers = p_par1;
  344.     break;
  345.   case CDCMD_HFSFIRST:
  346.     g_hfs_first = p_par1;
  347.     break;
  348.   case CDCMD_DATAEXT:
  349.     strcpy (g_data_fork_extension, (char *) p_par1);
  350.     break;
  351.   case CDCMD_RESOURCEEXT:
  352.     strcpy (g_resource_fork_extension, (char *) p_par1);
  353.     break;
  354.   default:
  355.     return 999;
  356.   }
  357.   return 0;
  358. }
  359.  
  360. #if !defined(NDEBUG) || defined(DEBUG_SECTORS)
  361.  
  362. char *typetostr (int ty)
  363. {
  364.     switch(ty) {
  365.     case ACTION_DIE:        return("DIE");
  366.     case ACTION_FINDUPDATE:     return("OPEN-RW");
  367.     case ACTION_FINDINPUT:    return("OPEN-OLD");
  368.     case ACTION_FINDOUTPUT:    return("OPEN-NEW");
  369.     case ACTION_READ:        return("READ");
  370.     case ACTION_WRITE:        return("WRITE");
  371.     case ACTION_END:        return("CLOSE");
  372.     case ACTION_SEEK:        return("SEEK");
  373.     case ACTION_EXAMINE_NEXT:    return("EXAMINE NEXT");
  374.     case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
  375.     case ACTION_INFO:        return("INFO");
  376.     case ACTION_DISK_INFO:    return("DISK INFO");
  377.     case ACTION_PARENT:     return("PARENTDIR");
  378.     case ACTION_DELETE_OBJECT:    return("DELETE");
  379.     case ACTION_CREATE_DIR:    return("CREATEDIR");
  380.     case ACTION_LOCATE_OBJECT:    return("LOCK");
  381.     case ACTION_COPY_DIR:    return("DUPLOCK");
  382.     case ACTION_FREE_LOCK:    return("FREELOCK");
  383.     case ACTION_SET_PROTECT:    return("SETPROTECT");
  384.     case ACTION_SET_COMMENT:    return("SETCOMMENT");
  385.     case ACTION_RENAME_OBJECT:    return("RENAME");
  386.     case ACTION_INHIBIT:    return("INHIBIT");
  387.     case ACTION_RENAME_DISK:    return("RENAME DISK");
  388.     case ACTION_MORE_CACHE:    return("MORE CACHE");
  389.     case ACTION_WAIT_CHAR:    return("WAIT FOR CHAR");
  390.     case ACTION_FLUSH:        return("FLUSH");
  391.     case ACTION_SCREEN_MODE:    return("SCREENMODE");
  392.     case ACTION_IS_FILESYSTEM:    return("IS_FILESYSTEM");
  393.     case ACTION_SAME_LOCK:      return("SAME_LOCK");
  394.     case ACTION_COPY_DIR_FH:    return("COPY_DIR_FH");
  395.     case ACTION_PARENT_FH:      return("PARENT_FH");
  396.     case ACTION_EXAMINE_FH:     return("EXAMINE_FH");
  397.     case ACTION_FH_FROM_LOCK:   return("FH_FROM_LOCK");
  398.     case ACTION_CURRENT_VOLUME: return("CURRENT_VOLUME");
  399.     case ACTION_READ_LINK:    return("READ LINK");
  400.     case ACTION_MAKE_LINK:    return("MAKE LINK");
  401.     case ACTION_USER:        return("USER");
  402.     default:            return("---------UNKNOWN-------");
  403.     }
  404. }
  405.  
  406. /*
  407.  *  DEBUGGING CODE.    You cannot make DOS library calls that access other
  408.  *  devices from within a DOS device driver because they use the same
  409.  *  message port as the driver.  If you need to make such calls you must
  410.  *  create a port and construct the DOS messages yourself.  I do not
  411.  *  do this.  To get debugging info out another PROCESS is created to which
  412.  *  debugging messages can be sent.
  413.  *
  414.  *  You want the priority of the debug process to be larger than the
  415.  *  priority of your DOS handler.  This is so if your DOS handler crashes
  416.  *  you have a better idea of where it died from the debugging messages
  417.  *  (remember that the two processes are asyncronous from each other).
  418.  */
  419.  
  420. /*
  421.  *  BTW, the DOS library used by debugmain() was actually opened by
  422.  *  the device driver.    Note: DummyMsg cannot be on debugmain()'s stack
  423.  *  since debugmain() goes away on the final handshake.
  424.  */
  425.  
  426. #ifdef LATTICE
  427. void __saveds debugmain (void)
  428. #else
  429. void debugmain (void)
  430. #endif    /* LATTICE */
  431. {
  432.     MSG *msg;
  433.     short len;
  434.     void *fh;
  435. #ifdef LOG_MESSAGES
  436.     void *out;
  437. #endif
  438.  
  439.     Dbport = CreateMsgPort ();
  440.     fh = (void *) Open ((UBYTE *) "con:0/0/640/100/debugwindow", 1006);
  441.     PutMsg(Dback, &DummyMsg);
  442. #ifdef LOG_MESSAGES
  443. #ifdef LOG_TO_PAR
  444.     out = (void *) Open ((UBYTE *) "PAR:", 1006);
  445. #else
  446.     out = (void *) Open ((UBYTE *) "ram:cd.log", 1006);
  447. #endif
  448. #endif
  449.     for (;;) {
  450.     WaitPort(Dbport);
  451.     msg = GetMsg(Dbport);
  452.     len = msg->mn_Length;
  453.     if (len == 0)
  454.         break;
  455.     --len;                  /*  Fix length up   */
  456.     Write((BPTR) fh, msg+1, len);
  457. #ifdef LOG_MESSAGES
  458.     Write((BPTR) out, msg+1, len);
  459. #endif
  460.     FreeMem(msg,sizeof(MSG)+len+1);
  461.     }
  462.     Close ((BPTR) fh);
  463. #ifdef LOG_MESSAGES
  464.     Close ((BPTR) out);
  465. #endif
  466.     DeleteMsgPort(Dbport);
  467.     PutMsg(Dback,&DummyMsg);          /*  Kill handshake  */
  468. }
  469.  
  470. void dbinit (void)
  471. {
  472.     TASK *task = FindTask(NULL);
  473.  
  474.     Dback = CreateMsgPort();
  475.     if (CreateNewProcTags (
  476.                NP_Entry, debugmain,
  477.                    NP_Name, "DEV_DB",
  478.                       NP_Priority, task->tc_Node.ln_Pri+1,
  479.                       NP_StackSize, 4096,
  480.                       TAG_DONE)) {
  481.       WaitPort(Dback);                    /* handshake startup    */
  482.       GetMsg(Dback);                    /* remove dummy msg     */
  483.       dbprintf("Debugger running: %s, %s, %s\n", TheVersion+6,
  484. #define asString(x) #x
  485. #if defined(LATTICE)
  486.            "SAS/C" asString(__VERSION__) "." asString(__REVISION__),
  487. #elif defined(__GNUC__)
  488.            "GNU C " __VERSION__,
  489. #else
  490.            "???",
  491. #endif
  492.                  __TIME__);
  493.  
  494.       dbprintf ("g_cd = %08lx\n", g_cd);
  495.     
  496.     };
  497. }
  498.  
  499. void dbuninit (void)
  500. {
  501.     MSG killmsg;
  502.  
  503.     if (Dbport) {
  504.     killmsg.mn_Length = 0;        /*    0 means die        */
  505.     PutMsg(Dbport,&killmsg);
  506.     WaitPort(Dback);        /*    He's dead jim!      */
  507.     GetMsg(Dback);
  508.     DeleteMsgPort(Dback);
  509.  
  510.     /*
  511.      *  Since the debug process is running at a greater priority, I
  512.      *  am pretty sure that it is guarenteed to be completely removed
  513.      *  before this task gets control again.  Still, it doesn't hurt...
  514.      */
  515.  
  516.     Delay(100);            /*    ensure he's dead    */
  517.     }
  518. }
  519.  
  520. void dbprintf (char *format, ...)
  521. {
  522.     va_list arg;
  523.     char buf[256];
  524.     MSG *msg;
  525.  
  526.     va_start (arg, format);
  527.     if (Dbport && !DBDisable) {
  528.     vsprintf (buf, format, arg);
  529.     msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
  530.     msg->mn_Length = strlen(buf)+1;     /*    Length NEVER 0    */
  531.     strcpy((char *) (msg+1), buf);
  532.     PutMsg(Dbport,msg);
  533.     }
  534.     va_end (arg);
  535. }
  536.  
  537. #endif /* !NDEBUG || DEBUG_SECTORS */
  538.